#!/usr/bin/env python3
import os
import shutil
import pandas as pd
from datetime import datetime, timedelta
from jinja2 import Template

# 基础目录配置
BASE_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
CONFIG_DIR = os.path.join(BASE_DIR, "config")
XUNJIAN_DIR = os.path.join(BASE_DIR, "xunjian")
HTML_DIR = os.path.join(BASE_DIR, "html_report")
DEVICE_HTML_DIR = os.path.join(HTML_DIR, "devices")
TEMPLATES_DIR = os.path.join(BASE_DIR, "templates")
STATIC_SRC_DIR = os.path.join(BASE_DIR, "static")  # 静态资源源文件
STATIC_DIR = os.path.join(HTML_DIR, "static")      # 静态资源输出目录

def copy_static_files():
    """复制静态资源到输出目录"""
    os.makedirs(os.path.join(STATIC_DIR, "css"), exist_ok=True)
    os.makedirs(os.path.join(STATIC_DIR, "js"), exist_ok=True)

    # 复制CSS
    css_src = os.path.join(STATIC_SRC_DIR, "css", "style.css")
    css_dst = os.path.join(STATIC_DIR, "css", "style.css")
    if os.path.exists(css_src):
        shutil.copy(css_src, css_dst)

    # 复制JS
    js_src = os.path.join(STATIC_SRC_DIR, "js", "scripts.js")
    js_dst = os.path.join(STATIC_DIR, "js", "scripts.js")
    if os.path.exists(js_src):
        shutil.copy(js_src, js_dst)

def load_devices_from_config():
    """从配置文件加载设备列表"""
    devices = []
    server_info = os.path.join(CONFIG_DIR, "servers", "server_info.txt")
    sw_info = os.path.join(CONFIG_DIR, "sws", "sw_info.txt")

    if os.path.exists(server_info):
        with open(server_info, 'r', encoding='utf-8') as f:
            for line in f:
                line = line.strip()
                if line and not line.startswith('#'):
                    parts = line.split()
                    if parts:
                        devices.append({
                            'name': parts[0],
                            'type': 'server',
                            'config_path': os.path.join(CONFIG_DIR, "servers", parts[0])
                        })

    if os.path.exists(sw_info):
        with open(sw_info, 'r', encoding='utf-8') as f:
            for line in f:
                line = line.strip()
                if line and not line.startswith('#'):
                    parts = [p.strip() for p in line.split(',')]
                    if parts:
                        devices.append({
                            'name': parts[0],
                            'type': 'switch',
                            'config_path': os.path.join(CONFIG_DIR, "sws", parts[0])
                        })
    return devices

def process_csv_file(csv_path):
    """处理CSV文件"""
    try:
        df = pd.read_csv(csv_path, keep_default_na=False, na_values=[])
        if df.empty:
            return df
        time_col = next((col for col in df.columns if any(kw in col.lower() for kw in ['时间', 'date', 'timestamp'])), None)
        if time_col:
            df[time_col] = pd.to_datetime(df[time_col], errors='coerce')
        return df
    except Exception as e:
        print(f"处理文件失败: {csv_path} - {str(e)}")
        return pd.DataFrame()

def get_recent_data(device_name, days=7):
    """获取最近数据"""
    data_frames = []
    for month_offset in [0, -1]:
        check_date = datetime.now() + timedelta(days=30*month_offset)
        year_month = check_date.strftime("%Y/%m")
        csv_path = os.path.join(XUNJIAN_DIR, year_month, f"{device_name}.csv")
        if os.path.exists(csv_path):
            df = process_csv_file(csv_path)
            if not df.empty:
                data_frames.append(df)
    return pd.concat(data_frames, ignore_index=True).drop_duplicates() if data_frames else pd.DataFrame()

def determine_device_status(df):
    """确定设备状态"""
    if df.empty:
        return 'unknown', ["无数据"], None, [], None
    time_col = next((col for col in df.columns if any(kw in col.lower() for kw in ['时间', 'date', 'timestamp'])), None)
    last_row = df.iloc[-1]
    status = 'online'
    details = []
    for col in df.columns:
        if col != time_col:
            val = str(last_row[col]).lower()
            if 'login error' in val:
                details.append(f"{col}: 通信失败")
                status = 'offline'
            elif val in ['down', 'fail', 'error', 'offline', '-', 'n/a']:
                details.append(f"{col}: 离线")
                status = 'offline'
            elif val in ['warning', 'degraded'] and status != 'offline':
                details.append(f"{col}: 警告")
                status = 'warning'
    return status, details, time_col, [last_row.to_dict()], last_row.get(time_col, 'N/A')

def generate_daily_report(devices, date_str):
    """生成今日巡检报告"""
    daily_report_path = os.path.join(HTML_DIR, "daily_report.html")
    with open(os.path.join(TEMPLATES_DIR, "daily_report_template.html"), 'r', encoding='utf-8') as f:
        daily_template = Template(f.read())

    # 获取当日数据
    daily_devices = []
    for device in devices:
        df = get_recent_data(device['name'], days=1)  # 只获取当天数据
        if not df.empty:
            status, details, time_col, _, latest_check = determine_device_status(df)
            device_data = {
                'name': device['name'],
                'type': device['type'],
                'status': status,
                'status_details': details,
                'latest_check': latest_check.strftime("%Y-%m-%d %H:%M:%S") if hasattr(latest_check, 'strftime') else latest_check,
                'columns': [col for col in df.columns if col != time_col],
                'time_column': time_col,
                'rows': df.to_dict('records')
            }
        else:
            device_data = {
                'name': device['name'],
                'type': device['type'],
                'status': 'unknown',
                'status_details': ["今日无巡检数据"],
                'latest_check': 'N/A',
                'columns': [],
                'time_column': None,
                'rows': []
            }
        daily_devices.append(device_data)

    # 生成报告
    with open(daily_report_path, 'w', encoding='utf-8') as f:
        f.write(daily_template.render(
            devices=daily_devices,
            report_date=date_str,
            today=datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        ))

def generate_reports():
    """生成报告主函数"""
    print("=== 开始生成巡检报告 ===")

    # 准备目录和静态文件
    os.makedirs(HTML_DIR, exist_ok=True)
    os.makedirs(DEVICE_HTML_DIR, exist_ok=True)
    copy_static_files()

    # 加载设备和日期
    devices = load_devices_from_config()
    date_str = datetime.now().strftime("%Y-%m-%d")

    # 生成今日报告
    generate_daily_report(devices, date_str)

    # 处理设备数据
    device_reports = []
    available_months = sorted({f"{d.year}-{d.month:02d}" for d in pd.date_range(end=datetime.now(), periods=12, freq='ME')})

    for device in devices:
        df = get_recent_data(device['name'])
        if not df.empty:
            status, details, time_col, _, latest_check = determine_device_status(df)
            device_data = {
                'name': device['name'],
                'type': device['type'],
                'status': status,
                'status_details': details,
                'latest_check': latest_check.strftime("%Y-%m-%d %H:%M:%S") if hasattr(latest_check, 'strftime') else latest_check,
                'columns': [col for col in df.columns if col != time_col],
                'time_column': time_col,
                'rows': df.to_dict('records')
            }
        else:
            device_data = {
                'name': device['name'],
                'type': device['type'],
                'status': 'unknown',
                'status_details': ["无巡检数据"],
                'latest_check': 'N/A',
                'columns': [],
                'time_column': None,
                'rows': []
            }
        device_reports.append(device_data)

    # 统计信息
    online_count = sum(1 for d in device_reports if d['status'] == 'online')
    warning_count = sum(1 for d in device_reports if d['status'] == 'warning')
    offline_count = sum(1 for d in device_reports if d['status'] in ['offline', 'unknown'])

    # 加载模板
    with open(os.path.join(TEMPLATES_DIR, "index_template.html"), 'r', encoding='utf-8') as f:
        index_template = Template(f.read())
    with open(os.path.join(TEMPLATES_DIR, "device_detail_template.html"), 'r', encoding='utf-8') as f:
        detail_template = Template(f.read())

    # 生成主页
    with open(os.path.join(HTML_DIR, "index.html"), 'w', encoding='utf-8') as f:
        f.write(index_template.render(
            devices=device_reports,
            total_devices=len(device_reports),
            online_count=online_count,
            warning_count=warning_count,
            offline_count=offline_count,
            available_months=available_months,
            today=datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        ))

    # 生成详情页
    for device in device_reports:
        with open(os.path.join(DEVICE_HTML_DIR, f"{device['name']}.html"), 'w', encoding='utf-8') as f:
            f.write(detail_template.render(
                device=device,
                highlight_cell=lambda v: 'login-error' if 'login error' in str(v).lower() else
                                      'status-offline' if str(v).lower() in ['down', 'fail', 'offline'] else
                                      'status-online' if str(v).lower() in ['up', 'ok', 'online'] else '',
                str=str,
                available_months=available_months
            ))

    print("=== 报告生成完成 ===")
    print(f"总设备数: {len(device_reports)}")
    print(f"正常设备: {online_count}")
    print(f"警告设备: {warning_count}")
    print(f"离线设备: {offline_count}")

if __name__ == "__main__":
    generate_reports()
